package com.cooper.scraper;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.content.Context;
import android.content.res.AssetManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Environment;
import android.util.Log;

import com.cooper.android.comm.FileUtils;

public class ScraperManager {

	private static ScraperManager instance;

	public static ScraperManager getInstance() {
		if (instance == null) {
			instance = new ScraperManager();
		}
		return instance;
	}

	private static final String SCAPER_STORE_DIR = ".cooper_soft/scapers/";

	private static final boolean DEBUG = false;

	private static final long UPDATE_TIME_LONG = 1 * 24 * 60 * 60 * 1000;

	private static final String ASSET_PATH = "scraper";

	private Map<String, String> scrapers = new HashMap<String, String>();

	protected ScraperManager() {
		super();
	}

	private String getScraperLocalFileName(String scraperId) {
		Matcher m = Pattern.compile("([^\\/\\s\\.]+?\\.xml)[^\\/]*$").matcher(
				scraperId);
		if (m.find()) {
			return m.group(1);
		} else {
			return FileUtils.stringToFileName(scraperId);
		}
	}

	private String getScraperLocalStoreDir() {
		return Environment.getExternalStorageDirectory().toString() + "/"
				+ SCAPER_STORE_DIR + "/";
	}

	public synchronized void cleanAllLocalScraper() {
		File scraperDir = new File(getScraperLocalStoreDir());
		if (scraperDir.exists()) {
			File[] scraperFiles = scraperDir.listFiles(new FileFilter() {

				@Override
				public boolean accept(File pathname) {
					return pathname.isFile()
							&& FileUtils.extractExtName(pathname).trim()
									.equals("xml");
				}
			});
			if (scraperFiles != null)
				for (File scraperFile : scraperFiles) {
					if (scraperFile.exists()) {
						scraperFile.delete();
					}
				}
		}
		scrapers.clear();
	}

	public synchronized void cleanLocalScraper(String scraperId) {
		File scrapeFile = new File(getScraperLocalStoreDir()
				+ getScraperLocalFileName(scraperId));
		if (scrapeFile.exists()) {
			scrapeFile.delete();
		}
		scrapers.remove(scraperId);
	}

	public synchronized String getScraper(Context context, String scraperId)
			throws ScraperException {
		String result = scrapers.get(scraperId);

		if (result == null || "".equals(result.trim())) {

			String storeDir = getScraperLocalStoreDir();
			File storeDirFile = new File(storeDir);
			if (!storeDirFile.exists() || !storeDirFile.isDirectory()) {
				storeDirFile.mkdirs();
			}

			if (Thread.currentThread().isInterrupted()) {
				return null;
			}
			String fileName = getScraperLocalFileName(scraperId);

			if (!DEBUG) {

				File scraperFile = new File(storeDir + fileName);
				if (scraperFile.exists()
						&& ((new Date().getTime() - scraperFile.lastModified()) < UPDATE_TIME_LONG)) {
					try {
						result = FileUtils.readTextFile(scraperFile
								.getAbsolutePath());
						Log.d("ScraperDownTask", "load from local file - "
								+ scraperId);
					} catch (Exception e) {
						Log.e("ScraperDownTask", e.getMessage(), e);
					}
				}
				if (result == null || "".equals(result.trim())) {
					NetworkInfo networkInfo = ((ConnectivityManager) context
							.getSystemService(Context.CONNECTIVITY_SERVICE))
							.getActiveNetworkInfo();
					if ((networkInfo != null)
							&& (NetworkInfo.State.CONNECTED == networkInfo
									.getState())
							&& (!HttpDownload.getInstance().getDownloadParams()
									.isOnlyWIFI() || (networkInfo.getType() == ConnectivityManager.TYPE_WIFI))
							&& (Environment.getExternalStorageState()
									.equals(Environment.MEDIA_MOUNTED))) {

						if (Thread.currentThread().isInterrupted()) {
							return null;
						}
						try {
							// HttpDownload httpDownload = new
							// HttpDownload(params);

							result = HttpDownload.getInstance().downloadPage(
									scraperId, false);

							Log.d("ScraperDownTask", "load from internet - "
									+ scraperId);
							try {
								if (scraperFile.exists()) {
									scraperFile.delete();
								}
								FileUtils.writerTextFile(
										scraperFile.getAbsolutePath(), result);
							} catch (Exception e) {
								Log.e("ScraperDownTask", e.getMessage(), e);
							}

						} catch (Exception e) {
							Log.e("ScraperDownTask", e.getMessage(), e);
						}
					}
				}
			}
			if (Thread.currentThread().isInterrupted()) {
				return null;
			}
			if (result == null || "".equals(result.trim())) {

				AssetManager am = context.getAssets();
				try {
					BufferedReader reader = new BufferedReader(
							new InputStreamReader(am.open(ASSET_PATH + "/"
									+ fileName)));
					try {
						StringBuffer scraperTxt = new StringBuffer();
						String line = reader.readLine();
						while (line != null) {
							scraperTxt.append(line);
							scraperTxt.append("\n");
							line = reader.readLine();
						}
						result = scraperTxt.toString();
						Log.d("ScraperDownTask", "load from assets - "
								+ scraperId);
					} finally {
						reader.close();
					}
				} catch (Exception e) {
					Log.e("ScraperDownTask", fileName + "|" + scraperId, e);
				}
			}
			scrapers.put(scraperId, result);
		}

		if (result != null && !"".equals(result.trim())) {
			return result;
		} else
			throw new ScraperException();
	}

}
